package com.zhoug.map2.location;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;


import com.zhoug.json2.GsonUtils;
import com.zhoug.logger2.Logger;
import com.zhoug.map2.Utils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import androidx.annotation.NonNull;

/**
 * @Author: zhoug
 * @Date: 2025-01-07
 * @Description:
 */
public class GpsLocationService implements LocationService {
    private static final String TAG = ">>>GpsLocationService";
    private static final boolean DEBUG = false;
    private static final String KEY_LOCATION = "ZLocation";
    private LocationManager mLocationManager;
    private Context mContext;
    private final List<OnLocationListener> mListeners = new ArrayList<>(); //定位监听集合

    private final Set<String> locationSources = new HashSet<>();
    private SharedPreferences mSharedPreferences;

    /**
     * 位置更新最小时间间隔
     */
    private long mLocationUpdateMinTime = 0;
    /**
     * 位置更新最小移动距离
     */
    private float mLocationUpdateMinDistance = 0.0f;
    private boolean mIsStart = false;
    private ZLocation mLocation;//定位结果
    private ExecutorService executor = Executors.newSingleThreadExecutor();

    public GpsLocationService(@NonNull Context context) {
        this.mContext = context;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mLocationManager = mContext.getSystemService(LocationManager.class);
        } else {
            mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
        }
        locationSources.add(LocationManager.GPS_PROVIDER);
        locationSources.add(LocationManager.NETWORK_PROVIDER);
        mSharedPreferences = context.getSharedPreferences("loc", Context.MODE_PRIVATE);
    }

    /**
     * 位置更新最小时间间隔
     *
     * @param locationUpdateMinTime
     */
    public void setLocationUpdateMinTime(long locationUpdateMinTime) {
        if (locationUpdateMinTime < 0) {
            this.mLocationUpdateMinTime = 0;
        } else {
            this.mLocationUpdateMinTime = locationUpdateMinTime;
        }
    }

    /**
     * 位置更新最小移动距离
     *
     * @param locationUpdateMinDistance
     */
    public void setLocationUpdateMinDistance(float locationUpdateMinDistance) {
        if (locationUpdateMinDistance < 0) {
            this.mLocationUpdateMinDistance = 0;
        } else {
            this.mLocationUpdateMinDistance = locationUpdateMinDistance;
        }
    }

    /**
     * GPS定位是否打开
     *
     * @return
     */
    public boolean isGpsOpen() {
        return Utils.isGpsOpen(mLocationManager);
    }


    /**
     * 启动定位sdk,启动后会默认立即发起定位请求
     */
    @SuppressLint("MissingPermission")
    @Override
    public void start() {
        if (mLocationManager != null) {
            mIsStart = true;
            _start();
        }
    }

    private void _start() {
        List<String> providers = mLocationManager.getProviders(true);
        if (providers.contains(LocationManager.GPS_PROVIDER)) {
            requestLocationUpdates(LocationManager.GPS_PROVIDER);
        } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
            requestLocationUpdates(LocationManager.NETWORK_PROVIDER);
        } else {
            Logger.e(TAG, "GPS and NetWork provider all disabled");
        }
    }

    @SuppressLint("MissingPermission")
    private void requestLocationUpdates(String provider) {
        if (mLocationManager != null) {
            try {
                if (DEBUG) {
                    Logger.d(TAG, "start location:" + provider);
                }
                mLocationManager.requestLocationUpdates(provider, mLocationUpdateMinTime,
                        mLocationUpdateMinDistance, mLocationListener);
            } catch (Throwable e) {
                Logger.e(TAG, "start location:" + e.getMessage());
            }
        }

    }

    /**
     * 停止定位sdk
     */
    @SuppressLint("MissingPermission")
    @Override
    public void stop() {
        if (mLocationManager != null && mIsStart) {
            if (DEBUG) {
                Logger.d(TAG, "stop location");
            }
            mIsStart = false;
            try {
                mLocationManager.removeUpdates(mLocationListener);
            } catch (Exception e) {
                Logger.e(TAG, "stop location:" + e.getMessage());
            }
        }
    }

    /**
     * 获取最新的定位成功的位置:最后一次成功定位的位置或缓存的位置
     *
     * @return
     */
    @Override
    public ZLocation getLastLocation() {
        return getLocationFromDiskCache();
    }

    /**
     * 移除定位监听
     *
     * @param onLocationListener {@link OnLocationListener}
     */
    @Override
    public void removeOnLocationListener(OnLocationListener onLocationListener) {
        mListeners.remove(onLocationListener);

    }

    /**
     * 注册定位监听
     *
     * @param onLocationListener {@link OnLocationListener}
     */
    @Override
    public void addOnLocationListener(OnLocationListener onLocationListener) {
        if (!mListeners.contains(onLocationListener)) {
            mListeners.add(onLocationListener);
        }

    }

    /**
     * 销毁
     */
    @Override
    public void destroy() {
        stop();
        mListeners.clear();
        mLocationListener = null;
        mLocationManager = null;
        mContext = null;
        mSharedPreferences = null;
        mLocation = null;
    }

    /**
     * 位置更新回掉
     */
    private LocationListener mLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            if (DEBUG) {
                if (mLocation == null) {
                    mLocation = new ZLocation();
                }

                mLocation.setState(ZLocation.State.SUCCESS);
                if (DEBUG) {
                    Logger.d(TAG, "onLocationChanged:location=" + location);
                }
                String provider = location.getProvider();
                mLocation.setLatLng(location.getLatitude(), location.getLongitude());
                if (LocationManager.GPS_PROVIDER.equals(provider)) {
                    mLocation.setType(ZLocation.TypeGps);
                } else if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
                    mLocation.setType(ZLocation.TypeNetWork);
                } else {
                    mLocation.setType(ZLocation.TypeCache);
                }
                mLocation.setAddress(null);
                keepLocationToDiskCache(mLocation);
                //回掉注册的监听器
                if (mListeners != null && !mListeners.isEmpty()) {
                    for (OnLocationListener locationListener : mListeners) {
                        if (locationListener != null) {
                            locationListener.onReceiveLocation(mLocation);
                        }
                    }
                }

            }
        }


        @Override
        public void onProviderEnabled(@NonNull String provider) {
            if (DEBUG) {
                Logger.d(TAG, "onProviderEnabled:" + provider);
            }
        }


        @Override
        public void onProviderDisabled(@NonNull String provider) {
            if (DEBUG) {
                Logger.d(TAG, "onProviderDisabled:" + provider);
            }
        }
    };

    /**
     * 缓存定位到xml
     */
    private void keepLocationToDiskCache(@NonNull ZLocation location) {
        if (executor != null && mSharedPreferences != null) {
            executor.execute(() -> {
                if (mSharedPreferences != null) {
                    SharedPreferences.Editor edit = mSharedPreferences.edit();
                    edit.putString(KEY_LOCATION, GsonUtils.getDefault().toJson(location));
                    edit.apply();
                }
            });
        }
    }

    /**
     * 从xml中获取缓存定位
     */
    private ZLocation getLocationFromDiskCache() {
        if (mSharedPreferences != null) {
            String string = mSharedPreferences.getString(KEY_LOCATION, null);
            if (string != null) {
                try {
                    return GsonUtils.getDefault().fromJson(string, ZLocation.class);
                } catch (Exception e) {
                    Logger.e(TAG, "getLocationFromDiskCache:" + e.getMessage());
                }
            }
        }
        return null;
    }

}
